#pragma once

#ifdef REMJOBNET_EXPORTS
   #define DLLDIR  __declspec(dllexport)   
#else
   #define DLLDIR  __declspec(dllimport)   
#endif 

#include "socket.h"
#include "packet.h"

using namespace std;

namespace remjob {

	class DLLDIR Logger {
	private:
		list<string> messages;
	public:	
		void log(string message);
		string getLog();
	};

	class DLLDIR Action {
	protected:
		Logger logger;
	public:
		virtual void run()=0;
		string getLog();
	};

	class DLLDIR ReceiveUDP : Action {
	public:
		ReceiveUDP(Packet *p);
		~ReceiveUDP();
		void run();
		string getFilename();

	protected:
		string filename;
		Packet *p; //il pacchetto con il comando che ha generato la richiesta di ricezione del file
	
	private:
		list<u_int> offset;
	};

	class DLLDIR ReceiveTCP : ReceiveUDP {
	
	public:
		ReceiveTCP(Packet *p, Socket *s);
		~ReceiveTCP();
		void run();
	};

	class DLLDIR CommandListener : Action {
	public:
		typedef void (*command_handler)(Packet *, Socket *);
		CommandListener(command_handler handler);
		~CommandListener();
		command_handler handler;
		void run();
	};

	class DLLDIR SendUDPCommand: Action {
	public:
		SendUDPCommand(Packet *p);
		~SendUDPCommand();
		void run();

	protected:
		Packet *p;
	};

	class DLLDIR Discovery: SendUDPCommand {
	public:
		typedef void (* discovery_handler)(Packet *p);
		discovery_handler handler;
		Discovery(Packet *p,discovery_handler handler);
		~Discovery();
		void run();
	};

	class DLLDIR SendTCPCommand: SendUDPCommand {
	public:
		SendTCPCommand(Packet *p, list<u_int> destinatari);
		~SendTCPCommand();
		void run();

	private:
		list<u_int> destinatari;
	};

	class DLLDIR SendFileUDP: Action {
	public:
		SendFileUDP(Packet *p, string filename);
		~SendFileUDP();
		void run();

	protected:
		Packet *p;
		string filename;
	};	
	
	class DLLDIR SendFileTCP: SendFileUDP {
	public:
		SendFileTCP(Socket *s, string filename);
		~SendFileTCP();
		void run();
	
	private:
		Socket *s;
	};
}
